﻿using System;
using System.Collections.Concurrent;
using System.Web;
using System.Web.SessionState;

namespace DemoLib.Providers.Web
{
    public class CustomSessionStateProvider : SessionStateStoreProviderBase
    {
        private readonly ConcurrentDictionary<string, SessionData> _sessions;
        public CustomSessionStateProvider()
        {
            _sessions = new ConcurrentDictionary<string, SessionData>();
        }
        public override void Dispose()
        {
            GC.SuppressFinalize(this);
        }

        public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback)
        {
            throw new NotImplementedException();
        }

        public override void InitializeRequest(HttpContext context)
        {
            ;
        }

        public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId,
                                                      out SessionStateActions actions)
        {
            locked = false;
            lockAge = new TimeSpan(1);
            lockId = _sessions[id].LockId;
            actions = _sessions[id].StateActions;
            return _sessions[id].Item;
        }

        public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge,
                                                               out object lockId, out SessionStateActions actions)
        {
            locked = false;
            lockAge = new TimeSpan(1);
            lockId = _sessions[id].LockId;
            actions = _sessions[id].StateActions;
            return _sessions[id].Item;
        }

        public override void ReleaseItemExclusive(HttpContext context, string id, object lockId)
        {
            
        }

        public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem)
        {
            _sessions.AddOrUpdate(id, new SessionData {Item = item, LockId = lockId},
                                  (k, v) =>
                                      {
                                          v.Item = item;
                                          v.LockId = lockId;
                                          return v;
                                      });
        }

        public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item)
        {
            SessionData sessionData;
            _sessions.TryRemove(id, out sessionData);
        }

        public override void ResetItemTimeout(HttpContext context, string id)
        {
            throw new NotImplementedException();
        }

        public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout)
        {
            var newSession = new SessionStateStoreData(new SessionStateItemCollection(), null, timeout);
            return newSession;
        }

        public override void CreateUninitializedItem(HttpContext context, string id, int timeout)
        {
            throw new NotImplementedException();
        }

        public override void EndRequest(HttpContext context)
        {
            ;
        }
    }

    internal class SessionData
    {
        public SessionStateStoreData Item { get; set; }
        public object LockId { get; set; }
        public SessionStateActions StateActions { get; set; }
    }
}